#include "PropertyParser.h"

#include "QStringParser.h"
#include "BoolParser.h"
#include "PropertyUnitParser.h"
#include "DoubleParser.h"

#include <QXmlStreamReader>
#include <QString>

namespace Ipc2581b
{

PropertyParser::PropertyParser(
    DoubleParser *&_valueParser
    , QStringParser *&_textParser
    , PropertyUnitParser *&_unitParser
    , DoubleParser *&_tolPlusParser
    , DoubleParser *&_tolMinusParser
    , DoubleParser *&_plusTolParser
    , DoubleParser *&_minusTolParser
    , BoolParser *&_tolPercentParser
    , DoubleParser *&_refValueParser
    , QStringParser *&_refTextParser
    , PropertyUnitParser *&_refUnitParser
    , QStringParser *&_layerOrGroupRefParser
    , QStringParser *&_commentParser
):    m_valueParser(_valueParser)
    , m_textParser(_textParser)
    , m_unitParser(_unitParser)
    , m_tolPlusParser(_tolPlusParser)
    , m_tolMinusParser(_tolMinusParser)
    , m_plusTolParser(_plusTolParser)
    , m_minusTolParser(_minusTolParser)
    , m_tolPercentParser(_tolPercentParser)
    , m_refValueParser(_refValueParser)
    , m_refTextParser(_refTextParser)
    , m_refUnitParser(_refUnitParser)
    , m_layerOrGroupRefParser(_layerOrGroupRefParser)
    , m_commentParser(_commentParser)
{

}

bool PropertyParser::parse(QXmlStreamReader *reader)
{
    /* Pre */

    m_result.reset(new Property());

    /* Attributes */

    QStringRef data;
    if (reader->attributes().hasAttribute(QStringLiteral("value")))
    {
        data = reader->attributes().value(QStringLiteral("value"));
        if (!m_valueParser->parse(reader, data))
            return false;
        m_result->valueOptional = Optional<Double>(m_valueParser->result());
    }
    if (reader->attributes().hasAttribute(QStringLiteral("text")))
    {
        data = reader->attributes().value(QStringLiteral("text"));
        if (!m_textParser->parse(reader, data))
            return false;
        m_result->textOptional = Optional<QString>(m_textParser->result());
    }
    if (reader->attributes().hasAttribute(QStringLiteral("unit")))
    {
        data = reader->attributes().value(QStringLiteral("unit"));
        if (!m_unitParser->parse(reader, data))
            return false;
        m_result->unitOptional = Optional<PropertyUnit>(m_unitParser->result());
    }
    if (reader->attributes().hasAttribute(QStringLiteral("tolPlus")))
    {
        data = reader->attributes().value(QStringLiteral("tolPlus"));
        if (!m_tolPlusParser->parse(reader, data))
            return false;
        m_result->tolPlusOptional = Optional<Double>(m_tolPlusParser->result());
    }
    if (reader->attributes().hasAttribute(QStringLiteral("tolMinus")))
    {
        data = reader->attributes().value(QStringLiteral("tolMinus"));
        if (!m_tolMinusParser->parse(reader, data))
            return false;
        m_result->tolMinusOptional = Optional<Double>(m_tolMinusParser->result());
    }
    if (reader->attributes().hasAttribute(QStringLiteral("plusTol")))
    {
        data = reader->attributes().value(QStringLiteral("plusTol"));
        if (!m_plusTolParser->parse(reader, data))
            return false;
        m_result->plusTolOptional = Optional<Double>(m_plusTolParser->result());
    }
    if (reader->attributes().hasAttribute(QStringLiteral("minusTol")))
    {
        data = reader->attributes().value(QStringLiteral("minusTol"));
        if (!m_minusTolParser->parse(reader, data))
            return false;
        m_result->minusTolOptional = Optional<Double>(m_minusTolParser->result());
    }
    if (reader->attributes().hasAttribute(QStringLiteral("tolPercent")))
    {
        data = reader->attributes().value(QStringLiteral("tolPercent"));
        if (!m_tolPercentParser->parse(reader, data))
            return false;
        m_result->tolPercentOptional = Optional<Bool>(m_tolPercentParser->result());
    }
    if (reader->attributes().hasAttribute(QStringLiteral("refValue")))
    {
        data = reader->attributes().value(QStringLiteral("refValue"));
        if (!m_refValueParser->parse(reader, data))
            return false;
        m_result->refValueOptional = Optional<Double>(m_refValueParser->result());
    }
    if (reader->attributes().hasAttribute(QStringLiteral("refText")))
    {
        data = reader->attributes().value(QStringLiteral("refText"));
        if (!m_refTextParser->parse(reader, data))
            return false;
        m_result->refTextOptional = Optional<QString>(m_refTextParser->result());
    }
    if (reader->attributes().hasAttribute(QStringLiteral("refUnit")))
    {
        data = reader->attributes().value(QStringLiteral("refUnit"));
        if (!m_refUnitParser->parse(reader, data))
            return false;
        m_result->refUnitOptional = Optional<PropertyUnit>(m_refUnitParser->result());
    }
    if (reader->attributes().hasAttribute(QStringLiteral("layerOrGroupRef")))
    {
        data = reader->attributes().value(QStringLiteral("layerOrGroupRef"));
        if (!m_layerOrGroupRefParser->parse(reader, data))
            return false;
        m_result->layerOrGroupRefOptional = Optional<QString>(m_layerOrGroupRefParser->result());
    }
    if (reader->attributes().hasAttribute(QStringLiteral("comment")))
    {
        data = reader->attributes().value(QStringLiteral("comment"));
        if (!m_commentParser->parse(reader, data))
            return false;
        m_result->commentOptional = Optional<QString>(m_commentParser->result());
    }

    /* Elements */

    while (reader->readNextStartElement())
    {
        auto name = reader->name();
            reader->skipCurrentElement();
    }

    /* Post */

    // TODO: Check multiplicity of elements/attributes

    return true;
}

Property *PropertyParser::result()
{
    return m_result.take();
}

}